package com.dly.blog.controller;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.dly.blog.annotation.IgnoreAccess;
import com.dly.blog.content.RedisContent;
import com.dly.blog.domain.config.ChatConfig;
import com.dly.blog.domain.dto.GptRequestDto;
import com.dly.blog.domain.dto.GptResponseDto;
import com.dly.blog.domain.dto.MessageContentDto;
import com.dly.blog.domain.enums.ChatType;
import com.dly.blog.domain.ro.ChatGptRO;
import com.dly.blog.exception.ChatExceptionEnum;
import com.dly.blog.msg.R;
import com.dly.blog.provider.user.UserProvider;
import com.dly.blog.service.ChatConfigService;
import com.dly.blog.service.ChatProxy;
import com.dly.blog.service.ChatService;
import com.dly.blog.utile.JsonUtils;
import com.dly.blog.utile.RedisUtils;
import com.dly.blog.utile.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/chat")
@RequiredArgsConstructor
@Tag(name = "OpenAi聊天模块")
@Slf4j
public class ChatController extends BaseController {

    private final ChatService chatService;

    private final UserProvider userProvider;

    private final ChatConfigService chatConfigService;

    @PostMapping(value = "/saveMessages")
    @Operation(summary = "ChatGpt信息保存接口：上下文长度为4条")
    public ResponseEntity<R<String>> saveMessages(@RequestBody @Validated ChatGptRO chatGptRO, BindingResult br) {
        return operate(() -> this.successDate(chatService.saveMessages(chatGptRO)), br);
    }

    @GetMapping(path = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @IgnoreAccess
    @Operation(summary = "ChatGpt流式聊天接口")
    public SseEmitter gptMvc(String uuid) {
       return chatService.gptMvc(uuid);
    }

    @Operation(summary = "获取用户剩余次数")
    @GetMapping("/frequency")
    public ResponseEntity<R<Integer>> getFrequency(){
        return operate(()-> this.successDate(userProvider.getFrequency()));
    }

    @Operation(summary = "获取用户配置")
    @GetMapping("/chatConfig")
    @PreAuthorize("hasRole('admin')")
    public ResponseEntity<R<ChatConfig>> getChatConfig(){
        return operate(()-> this.successDate(chatConfigService.get()));
    }

    @Operation(summary = "保存用户配置")
    @PostMapping("/chatConfig")
    @PreAuthorize("hasRole('admin')")
    public ResponseEntity<R<Void>> saveChatConfig(@RequestBody ChatConfig config){
        chatConfigService.save(config);
        return operate(this::success);
    }

    @GetMapping(value = "/v1/chat/completions", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @Operation(summary = "ChatGpt流式聊天接口")
    @IgnoreAccess
    public Flux<ServerSentEvent<Object>> gpt() {
        return chatService.gpt();
    }

    @GetMapping("/showMiniApp")
    @Operation(summary = "是否展示微信小程序登入页面")
    @IgnoreAccess
    public ResponseEntity<R<Boolean>> showWxMiniApp(){
        return operate(()-> this.successDate(chatService.showWxMiniApp()));
    }

    @PostMapping("/setShowMiniApp")
    @Operation(summary = "设置展示微信小程序登入页面")
    public ResponseEntity<R<Void>> setShowWxMiniApp(@RequestParam("b") Boolean b){
        chatService.setShowWxMiniApp(b);
        return operate(this::success);
    }

}
